<!DOCTYPE html>
<html>

	<head>
		<meta charset="utf-8">
		<title>构造函数and面向对象</title>
		<style>
			div {
				width: 50px;
				height: 50px;
				background-color: red;
			}

			.on {
				width: 100px;
				height: 100px;
			}
		</style>
	</head>

	<body>
	<div class="ss"></div>
		<script>
			//ES6 类的写法
			class CreatePerson{
				constructor(name,age){
					this.name = name 
					this.age = age
				}
				static a = 20
				showName(){
					console.log(this.name);
				}
			}
			let  person =new CreatePerson('张三',18)
			console.log('person',person);
			console.log(CreatePerson.a);
			person.showName()
			// function CreatePerson(name,age){
			// 	this.name = name  
			// 	this.age = age
			// 	this.height = height
			// 	this.weight = weight
			// }
			// CreatePerson.prototype.showName = function(){
			// 	console.log(this.name);
			// }
			// CreatePerson.prototype.sayHello = function(){
			// 	console.log('hello');
			// }
			// CreatePerson.a = 50
			
			class CreateStudent extends CreatePerson{
				constructor(name,age,className){
					super(name,age)
					this.className = className
				}
				showClass(){
					console.log(this.className);
				}
			}
			// function CreateStudent(name,age,className){
			// 	CreatePerson.call(this,name,age)
			// 	this.className = className
			// }
			// CreateStudent.prototype = new CreatePerson()
			// CreateStudent.prototype.constructor = CreateStudent
			// CreateStudent.prototype.showClass = function(){
			// 	console.log(this.className);
			// }
			
			let student = new CreateStudent('李四',16,168)
			console.log('student',student);
			student.showName()
			student.showClass()
			

			
			/**
			 * 当我们访问一个对象里面的某个属性的时候   如果该对象有这个属性 直接用 
			 * 如果没有该属性 就找 该对象里面的  __proto__ (等同于找 构造该对象的构造函数的 prototype 对象 )
			 * 构造函数的 prototype 对象  他也是一个对象(只要是对象就是由构造函数构造出来的)
			 * 当我们 prototype 里面有就直接用 如果没有该属性  就找  构造  prototype 这个对象的构造函数的 prototype属性
			 * 当找到 Object的 prototype 还没有找到  那就结束了    在往上找 就是 null
			 */
			
			/*
			思路  模式
			面向对象  编程思路
			1.1面向过程
			- 面向过程就是分析出解决问题所需要的步骤，然后用函数把这些步骤一步一步实现，使用的时候再一个一个的依次调用就可以了。
			1.2面向对象
			- 面向对象是把事务分解成为一个个对象，然后由对象之间分工与合作。
			1.3面向函数
			- 将一个个的功能全部 具象封装为一个个的函数
			### 1.3面向过程与面向对象对比
			面向过程                                                     |                                                      |
			| 优点 | 性能比面向对象高，适合跟硬件联系很紧密的东西，例如单片机就采用的面向过程编程。
			| 缺点 | 不易维护、不易复用、不易扩展  
			面向对象						   
			 易维护、易复用、易扩展，由于面向对象有封装、继承、多态性的特性，可以设计出
			 低耦合的系统，使系统 更加灵活、更加易于维护 |
			 性能比面向过程低   
																								 |
			js都是基于面向对象的语言   基本上很多的操作都是 对象的 点操作
			
			一.回顾 创建对象的方法 有哪些？
			 字面量  let  obj= {}
			 new Object()
			  如果需要 大量 类似的对象怎么创建？可以用函数 
			 
			 二. new关键字的作用  ***
			 
			   1. 在构造函数代码开始执行之前，创建一个空对象；
			   2. 修改this的指向，把this指向创建出来的空对象；
			   3. 执行函数的代码
			   4. 在函数完成之后，返回this---即创建出来的对象
			 
			 - 利用构造函数创建对象  ***
			  三.  - 构造函数
				 - ***构造函数：是一种特殊的函数，主要用来初始化对象，即为对象成员变量赋初始值，
				 它总与 new 运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来，然后封装到这个函数里面。
				 - 构造函数的封装格式：
				   function 构造函数名(形参1,形参2,形参3) {
						this.属性名1 = 参数1;
						this.属性名2 = 参数2;
						this.属性名3 = 参数3;
						this.方法名 = 函数体;
				   }
				 - 构造函数的调用格式
				   var obj = new 构造函数名(实参1，实参2，实参3)
				   以上代码中，obj即接收到构造函数创建出来的对象。
				 - 注意事项
				   1.   构造函数约定首字母大写。
				   2.   函数内的属性和方法前面需要添加 **this** ，表示当前对象的属性和方法。
				   3.   构造函数中**不需要 return 返回结果**。
				   4.   当我们创建对象的时候，**必须用 new 来调用构造函数**。
				   
			
			四.原型
				构造函数原型prototype  
					构造函数通过原型分配的函数跟属性是所有对象所共享的。
					JavaScript 规定，每一个构造函数都有一个prototype 属性，这个属性 指向生成这个
					构造函数的对象，而这个对象叫做原型对象，简称为原型。注意这个prototype就是一
					个对象，这个对象的所有属性和方法，都会被构造函数构造的对象(实例对象)所拥有。
					我们可以把那些不变的方法，直接定义在 prototype 对象上，这样所有对象的实例就可以共享这些方法。
					
					对象都会有一个属性 __proto__ 指向构造函数的 prototype 原型对象，之所以我们对象可以使用
					构造函数 prototype 原型对象的属性和方法，就是因为对象有 __proto__ 原型的存在。
					__proto__对象原型和原型对象 prototype 是等价的
					__proto__对象原型的意义就在于为对象的查找机制提供一个方向，或者说一条路线，但是它是一个
					非标准属性，因此实际开发中，不可以使用这个属性，它只是内部指向原型对象 prototype
				5.constructor属性
				对象原型（ __proto__）和构造函数（prototype）原型对象里面都有一个属性 constructor 
				属性 ，constructor 我们称为构造函数，因为它指回构造函数本身。
				
			五.原型链 ***
					  每一个实例对象又有一个__proto__属性，指向的构造函数的原型对象（prototype），构造函数的原型对象
				也是一个对象，也有__proto__属性，这样一层一层往上找就形成了原型链。 Object.prototype
			
			六.继承
				构造函数的继承 
				// 1. 父构造函数
				function Father(uname, age) {
				  // this 指向父构造函数的对象实例
				  this.uname = uname;
				  this.age = age;
				}
				Father.prototype.money = function() {
				  console.log(100000);
				 };
				 // 2 .子构造函数 
				  function Son(uname, age, score) {
					  // this 指向子构造函数的对象实例
					  Father.call(this, uname, age);
					  this.score = score;
				  }
				// Son.prototype = Father.prototype;  这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会跟着一起变化
				  Son.prototype = new Father();
				  // 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数
				  Son.prototype.constructor = Son;
				  // 这个是子构造函数专门的方法
				  Son.prototype.exam = function() {
					console.log('孩子要考试');
				
				  }
				  var son = new Son('小花', 18, 100);
				  console.log(son);
				
				
			七.类
			- 在 ES6 中新增加了类的概念，可以使用 class 关键字声明一个类，之后以这个类来实例化对象。
			类抽象了对象的公共部分，它泛指某一大类（class）对象特指某一个，通过类实例化一个具体的对象
			
			1. 通过class 关键字创建类, 类名我们还是习惯性定义首字母大写
			2. 类里面有个constructor 函数,可以接受传递过来的参数,同时返回实例对象
			3. constructor 函数 只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个函数,类也会自动生成这个函数
			4. 多个函数方法之间不需要添加逗号分隔
			5. 生成实例 new 不能省略
			6. 语法规范, 创建类 类名后面不要加小括号,生成实例 类名后面加小括号, 构造函数不需要加function
				class People {
					constructor(name,age,job){
						this.name = name
						this.age=age
						this.job = job
					}
					showJob(){
						console.log(this.job);
					}
				}
			
				****
				1.实例成员
					实例成员就是构造函数内部通过this添加的成员 ,实例成员只能通过实例化的对象来访问
				2.静态成员 
					在构造函数本身上添加的成员 ,静态成员只能通过构造函数来访问  Date.now()
				3.原型成员
					解决构造函数存在浪费内存的问题。
				
				类的继承
				   因为子类自己的this对象，必须先通过父类的构造函数完成塑造，得到与父类同样的实例属性和方法，
				   然后再对其进行加工，加上子类自己的实例属性和方法。如果不调用super方法，子类就得不到this对象。
					class A {
						constructor(a,b){
							this.a=a
							this.b=b
						}
						showA(){
							console.log(this.a);
						}
					}
					
					class B extends A {
						constructor(a,b,c){
							super(a,b)
							this.c=c
						}
					}
			
			
			
			 
				   
			 
			八.构造函数跟类的区别
			
			构造函数，如 Stars()，抽象了对象的公共部分，封装到了函数里面，它泛指某一大类（class）
			创建对象，如 new Stars()，特指某一个，通过 new 关键字创建对象的过程我们也称为对象实例化
			
			
			class必须使用new调用，不用new调用会报错。普通构造函数不用new也可以执行
			最后还有一点 是类总是使用严格模式的。这意味着类构造中的所有代码都自动处于严格模式
			
			*/
		</script>
	</body>

</html>